home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / lib / awf / pass2.base < prev    next >
Text File  |  1995-05-16  |  21KB  |  589 lines

  1. # second pass:  interpretation of directives
  2. # A macro-set-specific portion gets interpolated into this at the "#include"
  3. # line.  As a minimum, it must deal with .^b and .^e and with any input traps.
  4. BEGIN {
  5.        # stuff for output to third pass
  6.        nobreak = -1
  7.        dobreak = -2
  8.        message = -3
  9.        OFS = "\t"
  10.  
  11.        # special-character table; this one character needs to be hardcoded
  12.        chars[" "] = " " ; charwidths[" "] = 1
  13.  
  14.        debug["e"] = 0          # just to make it an array
  15.        strings["a"] = ""       # just to make it an array
  16.        numbers["a"] = 0        # just to make it an array
  17.        hyphens["a"] = ""       # just to make it an array
  18.        hyphenwidths["a"] = ""  # just to make it an array
  19.  
  20.        # stuff for expression decoding
  21.        signfactor["+"] = 1
  22.        signfactor["-"] = -1
  23.        scale["i"] = 240
  24.        scale["c"] = 240*50/127
  25.        scale["P"] = 240/6
  26.        # we get m, n, and v when we see .^r
  27.        scale["p"] = 240/72
  28.        scale["u"] = 1
  29.  
  30.        # stuff for basic parameters that just get passed to third pass
  31.        parms["in"] = 0         # just to make it an array
  32.        prevparms["in"] = 0     # just to make it an array
  33.        setcmd["ll"] = "linelen"
  34.        setcmd["in"] = "indent"
  35.        setcmd["ti"] = "tempindent"
  36.        setcmd["po"] = "pageoffset"
  37.        setcmd["pl"] = "pagelen"
  38.  
  39.        # did last word end with \c ?  (in which case, it's still in "word")
  40.        backc = 0
  41.  
  42.        # stuff for error reporting
  43.        il = 0                  # input line number
  44.        lockil = 0              # il is locked, we're inside a macro
  45.        inname = "?"            # input filename
  46.        msg = message "\t"      # later picks up filename etc.
  47.  
  48.        # current input trap
  49.        afternext = ""
  50. }
  51. {
  52.        if (!lockil)
  53.                il++
  54.        msg = message "\t" inname "," il ": "
  55.        # fallthrough
  56. }
  57. /^[ \t]*$/ {                   # empty line
  58.        print dobreak, "space"
  59.        next
  60. }
  61. /^[ \t]/ {                     # line starting with white space
  62.        print dobreak, "flush"
  63.        print 0, ""             # empty word
  64.        # fallthrough
  65. }
  66. /^[^.]/ {                      # text
  67.        # dispose of the easy case
  68.        if (font == "R" && $0 !~ /\\|\t|-|  / && !backc && afternext == "") {
  69.                for (i = 1; i <= NF; i++)
  70.                        print length($i), $i
  71.                if ($0 ~ /[.!?:][\])'"*]*$/)
  72.                        print nobreak, "gap", 2
  73.                if (centering > 0) {
  74.                        print dobreak, "center"
  75.                        centering--
  76.                } else if (!fill)
  77.                        print dobreak, "flush"
  78.                next
  79.        }
  80.  
  81.        # the hard case, needs a character-by-character scan
  82.        s = $0 " "              # the space flushes the last word
  83.        n = 1                   # current position in s
  84.        inword = 0              # have we been processing a word?
  85.        period = ""             # "." if this word ended a sentence
  86.        nsp = 0                 # count of spaces seen so far
  87.        tabpos = 0              # which tab position was used last
  88.        while (n <= length(s)) {
  89.                c = substr(s, n, 1)
  90.  
  91.                # handle state transitions
  92.                if (c == " " || c == "\t") {
  93.                        if (inword) {           # ends word
  94.                                if (!backc) {
  95.                                        print wordlen, word
  96.                                        if (usedhyphen)
  97.                                                print nobreak, "nohyphen"
  98.                                }
  99.                                inword = 0
  100.                                nsp = 0
  101.                        }
  102.                } else {
  103.                        if (!inword) {          # begins word
  104.                                if (!backc) {
  105.                                        word = ""
  106.                                        wordlen = 0
  107.                                        usedhyphen = 0
  108.                                }
  109.                                backc = 0
  110.                                inword = 1
  111.                                if (nsp > 1)
  112.                                        print nobreak, "gap", nsp
  113.                        }
  114.                }
  115.  
  116.                # deal with the character
  117.                if (c == " ") {
  118.                        nsp++
  119.                        if (n != length(s))     # not the trailing flusher
  120.                                period = ""
  121.                } else if (c == "\t") {
  122.                        # not really right, should be based on input position
  123.                        # also, one space following tab gets ignored
  124.                        tabpos++
  125.                        if (tabpos <= ntabs)
  126.                                print nobreak, "tabto", tabs[tabpos]
  127.                        nsp = 0
  128.                        period = ""
  129.                } else if (c == "-" && wordlen > 0) {
  130.                        # hyphen within word
  131.                        print wordlen, word, hyphenwidths[font]
  132.                        print nobreak, "userhyphen", hyphens[font], hyphenwidths[font]
  133.                        word = ""
  134.                        wordlen = 0
  135.                        period = ""
  136.                        usedhyphen = 1
  137.                } else if (c != "\\") {
  138.                        # ordinary character
  139.                        if (font == "B")
  140.                                word = word c "\b" c "\b" c
  141.                        else if (font == "I" && c ~ /[a-zA-Z0-9]/)
  142.                                word = word "_\b" c
  143.                        else
  144.                                word = word c
  145.                        wordlen++
  146.                        if (c ~ /[.!?:]/)
  147.                                period = "."
  148.                        else if (c !~ /[\])'"*]/)
  149.                                period = ""
  150.                } else {                        # backslash
  151.                        n++
  152.                        c = substr(s, n, 1)
  153.                        if (c == "f") {
  154.                                # font change
  155.                                n++
  156.                                code = substr(s, n, 1)
  157.                                if (code == "(") {
  158.                                        n++
  159.                                        code = substr(s, n, 2)
  160.                                        n++
  161.                                }
  162.                                if (code == "P")
  163.                                        font = prevfont
  164.                                else if (fontok[code] == "")
  165.                                        print msg "unknown font `" code "'"
  166.                                else {
  167.                                        prevfont = font
  168.                                        font = code
  169.                                }
  170.                        } else if (c == "n") {
  171.                                # number-register value
  172.                                n++
  173.                                code = substr(s, n, 1)
  174.                                if (code == "(") {
  175.                                        n++
  176.                                        code = substr(s, n, 2)
  177.                                        n++
  178.                                }
  179.                                s = substr(s, 1, n) numbers[code] substr(s, n+1)
  180.                        } else if (c == "s") {
  181.                                # size change
  182.                                n++
  183.                                if (substr(s, n, 1) ~ /[0-9]/)
  184.                                        n++
  185.                                # just ignore it
  186.                        } else if (c == "c")
  187.                                # word continuation
  188.                                backc = 1
  189.                        else if (c == "*") {
  190.                                # string-variable value
  191.                                n++
  192.                                code = substr(s, n, 1)
  193.                                if (code == "(") {
  194.                                        n++
  195.                                        code = substr(s, n, 2)
  196.                                        n++
  197.                                }
  198.                                s = substr(s, 1, n) strings[code] substr(s, n+1)
  199.                        } else if (c == "%") {
  200.                                # discretionary hyphen
  201.                                if (wordlen > 0) {
  202.                                        print wordlen, word, hyphenwidths[font]
  203.                                        print nobreak, "hyphen", hyphens[font], hyphenwidths[font]
  204.                                        word = ""
  205.                                        wordlen = 0
  206.                                        usedhyphen = 1
  207.                                }
  208.                        } else if (c == "(" && substr(s, n+1, 2) == "em" && \
  209.                                                        chars["em"] != "") {
  210.                                # em-dash, special case due to hyphenation
  211.                                n += 2
  212.                                emw = charwidths["em"]
  213.                                print wordlen, word, emw
  214.                                print nobreak, "userhyphen", chars["em"], emw
  215.                                word = ""
  216.                                wordlen = 0
  217.                                period = ""
  218.                                usedhyphen = 1
  219.                        } else {
  220.                                # special-character name
  221.                                code = c
  222.                                if (code == "(") {
  223.                                        n++
  224.                                        code = substr(s, n, 2)
  225.                                        n++
  226.                                }
  227.                                word = word chars[code]
  228.                                wordlen += charwidths[code]
  229.                                period = ""
  230.                        }
  231.                }
  232.  
  233.                # on to the next character, at last
  234.                n++
  235.        }
  236.  
  237.        # end-of-line processing
  238.        if (!backc) {
  239.                if (period == ".")
  240.                        print nobreak, "gap", 2
  241.                if (centering > 0) {
  242.                        print dobreak, "center"
  243.                        centering--
  244.                } else if (!fill)
  245.                        print dobreak, "flush"
  246.        }
  247.  
  248.        # if no input trap, we're done
  249.        if (afternext == "")
  250.                next
  251.  
  252.        # if there is an input trap, fall into the macro-dependent section
  253. }
  254. #
  255. #
  256. #
  257. # at this point we plug in the macro-specific stuff, keyed on the next line
  258. #include                       note that this is an awk comment
  259. #
  260. #
  261. #
  262. /^\.it/ {                      # plant an input trap, sort of
  263.        if (NF > 1 && $2 != 1)
  264.                print msg ".it first argument must be 1"
  265.        if (NF > 2)
  266.                afternext = afternext "," $3
  267.        else
  268.                afternext = ""
  269.        next
  270. }
  271. /^\.\^r cpi / {                        # set resolutions, in cpi:  .^r cpi hor vert
  272.        scale["m"] = 240/$3
  273.        scale["n"] = 240/$3
  274.        scale["v"] = 240/$4
  275.        next
  276. }
  277. /^\.(ta|ll|in|ti|po|ne|sp|pl|nr)/ {    # expression processing
  278.        # sort out default scale factor
  279.        if ($1 ~ /^\.(ne|sp|pl)/)
  280.                exprscale = "v"
  281.        else if ($1 ~ /^\.(nr)/)
  282.                exprscale = "u"
  283.        else
  284.                exprscale = "n"
  285.  
  286.        # which argument should we start with?
  287.        offset = length($1) + 1
  288.        if ($1 == ".nr")
  289.                offset += length($2) + 1
  290.  
  291.        # beginning of debugging message
  292.        if (debug["e"])
  293.                printf "%s ", msg substr($0, 1, offset)
  294.  
  295.        # do the expressions
  296.        s = substr($0, offset+1)
  297.        n = 1
  298.        while (s != "") {
  299.                while (s ~ /^[ \t]/)
  300.                        s = substr(s, 2)
  301.  
  302.                # an initial sign is magic
  303.                ssign = ""
  304.                if (s ~ /^[+-]/) {
  305.                        ssign = substr(s, 1, 1)
  306.                        s = substr(s, 2)
  307.                }
  308.                s = "+" s       # this is an un-magic addition operator
  309.  
  310.                # process terms
  311.                sval = 0
  312.                # there is no portable way to put a slash in a regexp
  313.                while (s ~ /^[+*%)-]/ || substr(s, 1, 1) == "/") {
  314.                        # figure out what it is and what it contributes
  315.                        if (debug["e"] > 1)
  316.                                print "s=`" s "'"
  317.                        termop = substr(s, 1, 1)
  318.                        s = substr(s, 2)
  319.                        termscale = exprscale
  320.                        if (termop == ")") {
  321.                                if (debug["e"] > 1)
  322.                                        print "pop " valstack[vsp] " " opstack[vsp] " with " sval
  323.                                termval = sval
  324.                                sval = valstack[vsp]
  325.                                termop = opstack[vsp]
  326.                                vsp--
  327.                                termscale = "u"
  328.                        } else if (s ~ /^\(/) {
  329.                                if (debug["e"] > 1)
  330.                                        print "push " sval " " termop
  331.                                vsp++
  332.                                valstack[vsp] = sval
  333.                                opstack[vsp] = termop
  334.                                sval = 0
  335.                                termop = "+"    # dummy op and value
  336.                                termval = 0
  337.                                s = "+" substr(s, 2)
  338.                        } else if (s ~ /^\\w/) {
  339.                                delim = substr(s, 3, 1)
  340.                                s = substr(s, 4)
  341.                                endp = index(s, delim)
  342.                                if (endp == 0)
  343.                                        endp = length(s) + 1
  344.                                termval = (endp - 1) * scale["n"]       # crude
  345.                                s = substr(s, endp+1)
  346.                        } else if (s ~ /^\\n/) {
  347.                                if (s ~ /^\\n\(/) {
  348.                                        code = substr(s, 4, 2)
  349.                                        s = substr(s, 6)
  350.                                } else {
  351.                                        code = substr(s, 3, 1)
  352.                                        s = substr(s, 4)
  353.                                }
  354.                                termval = numbers[code]
  355.                        } else if (s ~ /^[0-9.]/) {
  356.                                for (endp = 1; endp <= length(s); endp++)
  357.                                        if (substr(s, endp, 1) !~ /[0-9.]/)
  358.                                                break
  359.                                termval = substr(s, 1, endp-1) + 0
  360.                                s = substr(s, endp)
  361.                        }
  362.  
  363.                        # add it in, with scaling factor
  364.                        c = substr(s, 1, 1)
  365.                        if (scale[c] != "") {
  366.                                termval *= scale[c]
  367.                                s = substr(s, 2)
  368.                        } else
  369.                                termval *= scale[termscale]
  370.                        if (termop == "+")
  371.                                sval += termval
  372.                        else if (termop == "-")
  373.                                sval -= termval
  374.                        else if (termop == "*")
  375.                                sval *= termval
  376.                        else if (termop == "/")
  377.                                sval = int(sval) / int(termval)
  378.                        else if (termop == "%")
  379.                                sval = int(sval) % int(termval)
  380.                }
  381.  
  382.                # remember the value, print if debugging
  383.                expr[n] = sval
  384.                exprsign[n] = ssign
  385.                iexpr[n] = signfactor[ssign] * sval     # convenience
  386.                if (debug["e"])
  387.                        printf "%s ", ssign "(" sval ")"
  388.  
  389.                # proceed to next, skipping trash if necessary
  390.                while (s ~ /^[^ \t]/)
  391.                        s = substr(s, 2)
  392.                n++
  393.        }
  394.  
  395.        # final cleanup
  396.        nexprs = n - 1
  397.        if (debug["e"])
  398.                printf "\n"
  399.  
  400.        # fallthrough
  401. }
  402. /^\.(ll|in|ti|po|pl)/ {                # common code for set-parameter requests
  403.        # relies on expression processing, including setting of exprscale
  404.        name = substr($1, 2, 2)
  405.        n = parms[name]
  406.        if (nexprs == 0)
  407.                n = prevparms[name]
  408.        else if (exprsign[1] == "" || name == "ti")
  409.                n = expr[1] / scale[exprscale]
  410.        else
  411.                n += iexpr[1] / scale[exprscale]
  412.        prevparms[name] = parms[name]
  413.        parms[name] = int(n)
  414.        print dobreak, setcmd[name], parms[name]
  415.        next
  416. }
  417. /^\.nr/ {
  418.        # relies on expression processing
  419.        n = numbers[$2]
  420.        if (exprsign[1] == "")
  421.                n = expr[1]
  422.        else
  423.                n += iexpr[1]
  424.        numbers[$2] = int(n)
  425.        next
  426. }
  427. /^\.ne/ {
  428.        # relies on expression processing
  429.        print dobreak, "need", int(expr[1]/scale["v"] + 0.99)
  430.        next
  431. }
  432. /^\.sp/ {
  433.        # relies on expression processing
  434.        if (nexprs == 0)
  435.                i = 1
  436.        else
  437.                i = int(expr[1]/scale["v"] + 0.99)
  438.        for (; i > 0; i--)
  439.                print dobreak, "space"
  440.        next
  441. }
  442. /^\.ta/ {
  443.        # relies on expression processing
  444.        tabstop = 0
  445.        for (n = 1; n <= nexprs; n++) {
  446.                if (exprsign[n] == "")
  447.                        tabstop = expr[n]
  448.                else
  449.                        tabstop += iexpr[n]
  450.                tabs[n] = int(tabstop/scale["n"])
  451.        }
  452.        ntabs = nexprs
  453.        next
  454. }
  455. /^\.ft/ {
  456.        if (NF > 1)
  457.                code = $2
  458.        else
  459.                code = "P"
  460.  
  461.        if (code == "P")
  462.                font = prevfont
  463.        else if (fontok[code] == "")
  464.                print msg "unknown font `" code "'"
  465.        else {
  466.                prevfont = font
  467.                font = code
  468.        }
  469.        next
  470. }
  471. /^\.br/ {
  472.        print dobreak, "flush"
  473.        next
  474. }
  475. /^\.ds/ {
  476.        # note, macro-set-specific code often looks at .ds as well
  477.        if ($3 !~ /^"/)
  478.                strings[$2] = $3
  479.        else
  480.                strings[$2] = substr($0, index($0, "\"")+1)
  481.        next
  482. }
  483. /^\.ns/ {
  484.        print nobreak, "nospace"
  485.        next
  486. }
  487. /^\.rs/ {
  488.        print nobreak, "yesspace"
  489.        next
  490. }
  491. /^\.ad/ {
  492.        print nobreak, "both"
  493.        next
  494. }
  495. /^\.na/ {
  496.        print nobreak, "left"
  497.        next
  498. }
  499. /^\.nf/ {
  500.        fill = 0
  501.        print dobreak, "flush"
  502.        next
  503. }
  504. /^\.fi/ {
  505.        fill = 1
  506.        print dobreak, "flush"
  507.        next
  508. }
  509. /^\.\^x/ {                     # direct errors to this file:  .^x filename
  510.        print nobreak, "errsto", $2
  511.        next
  512. }
  513. /^\.\^c/ {                     # define character:  .^c name width text
  514.        if ($4 ~ /^"/)
  515.                s = substr($0, index($0, "\"")+1)
  516.        else
  517.                s = $4
  518.        ns = ""
  519.        while ((n = index(s, "\\")) > 0) {
  520.                if (n > 1)
  521.                        ns = ns substr(s, 1, n-1)
  522.                n++
  523.                c = substr(s, n, 1)
  524.                if (c == "\\")
  525.                        ns = ns "\\"
  526.                else if (c == "b")
  527.                        ns = ns "\b"
  528.                s = substr(s, n+1)
  529.        }
  530.        ns = ns s
  531.        if ($2 == "hy") {
  532.                hyphens[font] = ns
  533.                hyphenwidths[font] = $3
  534.        } else {
  535.                chars[$2] = ns
  536.                charwidths[$2] = $3
  537.        }
  538.        next
  539. }
  540. /^\.\^f/ {                     # this font is okay:  .^f fontname
  541.        # someday, this might take font-change codes as further arguments
  542.        fontok[$2] = "yes"
  543.        next
  544. }
  545. /^\.tm/ {
  546.        print msg $0
  547.        next
  548. }
  549. /^\.ps/ {
  550.        # ignore
  551.        next
  552. }
  553. /^\.ce/ {
  554.        if (NF > 1)
  555.                centering = $2
  556.        else
  557.                centering = 1
  558.        next
  559. }
  560. /^\.bp/ {
  561.        print dobreak, "need", 999
  562.        next
  563. }
  564. /^\.\^d/ {                     # debug control:  .^d debugvar value
  565.        debug[$2] = $3
  566.        next
  567. }
  568. /^\.\^#/ {                     # set line number of next line: .^# no file
  569.        il = $2 - 1
  570.        lockil = 0
  571.        inname = $3
  572.        next
  573. }
  574. /^\.\^=/ {                     # lock line number to value:  .^= no file
  575.        il = $2
  576.        lockil = 1
  577.        inname = $3
  578.        next
  579. }
  580. /^\.\\"/ {                     # comment
  581.        next
  582. }
  583. /^\./ {
  584.        print msg "command `" $1 "' unsupported or unknown"
  585. }
  586. END {
  587.        print dobreak, "need", 999      # flush page
  588. }
  589.